# -*- coding: utf-8 -*-

# -------------------------------
# Author    : linlingwei
# Email     : 951035650@qq.com
# File Name : fBrow.py
# Date      : 2019/8/26 
# IDE       : PyCharm
# Version   : 1.0.1
# -------------------------------
# 20190830 : beta 0.0.1
# 20190917 : beta 0.0.2
import traceback
import maya.cmds as mc
import maya.mel as mel

import configs.constants.facial_constant as fc
import configs.constants.global_constant as gc
import configs.constants.suffix_constant as sc
import configs.constants.nodeType_constant as ntc
import configs.constants.attribute_constant as ac

import scripts.commonCmds as con
reload(con)
import scripts.curveCmds as cr

import rig.facial.fCore as fCore
reload(fCore)



class Brow(fCore.FacialCore):
    """
    version beta 1.0
    """
    
    def __init__(self):
        super(Brow,self).__init__(fc.brow)
        self.transform_init()
        self.org_attr = [fc.inn,fc.innSup,
                    fc.mid,
                    fc.out,]
        
        
        tmp_ = con.lname("tmp", fc.brow)
        tmp_sr_crv = con.lname("tmp", fc.brow, "slider", fc.main, sc.sCrv)
    def blendShape_list(self):
        """
        Create driver bridge.
        :return:
        """
        attrlist = self.org_attr
        
        for lr in [fc.lf,fc.rt]:
            for attr in attrlist:
                for tag in [fc.ul,fc.lr]:
                    for pn in [fc.pos,fc.neg]:
                        mc.addAttr(self.local_static,ln=con.lname(lr,attr,tag,pn),
                                   at="float",dv=0,max=10,min=0,k=True)
                        mc.addAttr(self.local_static, ln=con.lname(lr, attr,fc.rot, tag, pn),
                                   at="float", dv=0, max=10, min=0,k=True)

        return attrlist
    
    def static_driver(self, prefix, tag, incrv):
        """
        
        控制留在原地的 bezier 曲线，传导出驱动值到 bridge。
        
        :param prefix: left or right prefix.
        :param tag: special tag.
        :param incrv: input curve reference.
        :return: local bridge.
        """
        _tag = con.lname(prefix, tag)
        lname = con.lname(_tag, con.selfFuncName())
        lstatic = mc.createNode(ntc.tTransform,name=con.lname(lname,fc.static),parent=self.local_static)
        mc.hide(lstatic)
        driCrv = con.lname(lname, sc.sCrv)
        pt = ([0,0,0],[1,0,0],[3,0,0],[5,0,0],[7,0,0],[9,0,0],[10,0,0])
        _tmp = mc.curve(p=pt,bezier=True,d=3)
        mc.rename(_tmp,driCrv)
        
        mc.addAttr(lstatic,ln="ratio",at = "float",dv=1,min=0,k=True)
        
        _crv = con.copyCurve(incrv, name=_tag + "_tttmp")
        mel.eval('rebuildCurve -ch 0 -rpo 1 -rt 0 -end 1 -kr 0 -kcp 1 -kep 1 -kt 0 -s 0 -d 3 -tol 0.01 "%s";'%_crv)
        _cvs = mc.ls(incrv+".cv[*]",fl=True)
        
        # frameCache = mc.createNode(ntc.tFrameCache,name = con.lname(lname,sc.sFc))
        # mc.setKeyframe(frameCache+".s", t=0, v=0,itt="linear",ott="linear")
        attr = con.lname(lname, sc.sFc)
        mc.addAttr(self.local_static,ln=attr,at="float",k=True)
        mc.setKeyframe(con.lAttr(self.local_static,attr), t=0, v=0, itt="linear", ott="linear")
        dri_fc = con.lname(self.local_static,attr)
        for i,cv in enumerate(_cvs):
            par = con.getObjInCrvParameter(_crv,cv)
            # npoc = mc.createNode(ntc.tNearestPointOnCurve,name=con.lname(lname,i,sc.sNpoc))
            npoc = mc.createNode(ntc.tPointOnCurveInfo,name=con.lname(lname,i,sc.sPoci))
            mc.connectAttr(con.findRelatedShape(driCrv)+".ws",npoc+".ic")
            # print par*10
            frameCache = mc.createNode(ntc.tFrameCache, name=con.lname(lname, sc.sFc))
            mc.connectAttr(dri_fc+".o",frameCache+".s")
            mc.setAttr(frameCache+".vt",par*10)
            mc.setKeyframe(con.lAttr(self.local_static,attr), t=par*10, v=par, itt="linear", ott="linear")
            mc.setAttr(npoc+".top",1)
            mc.connectAttr(frameCache+".v",npoc+".pr")
            # mc.setAttr(npoc+".ip",,0,0)

            mc.addAttr(lstatic,ln="index_%s"%i,at="float",dv=0,k=True)
            ratio_mdl = mc.createNode(ntc.tMultDoubleLinear,name = con.lname(lname,i,sc.sMdl))
            mc.connectAttr(npoc+".py",ratio_mdl+".i1")
            mc.connectAttr(lstatic+".ratio",ratio_mdl+".i2")
            mc.connectAttr(ratio_mdl+".o",con.lAttr(lstatic,"index_%s"%i))
        
        cvs = mc.ls(driCrv+".cv[*]",fl=True)
        loc_list = list()
        for i,cv in enumerate(cvs):
            loc = mc.spaceLocator(name = con.lname(lname,i,sc.sLoc))[0]
            x,y,z = mc.xform(cv,q=True,t=True,ws=True)
            mc.setAttr(loc+".t",x,y,z)
            mc.parent(loc,lstatic)
            locShape = con.findRelatedShape(loc)
            mc.connectAttr(locShape+".wp",cv)
            # mc.connectAttr()
            loc_list.append(loc)
        
        mc.parent(loc_list[2],loc_list[4],loc_list[3])
        [con.emptyGroup(_) for _ in loc_list]

        _loc0_out = con.objToType(loc_list[1], name=loc_list[0] + "_out", mode=2)
        mc.parent(_loc0_out,loc_list[0])
        mc.pointConstraint(_loc0_out,loc_list[2],loc_list[1]+"_Con",mo=True,skip=["x","z"])
        
        _loc0_out = con.objToType(loc_list[-2], name=loc_list[-1] + "_out", mode=2)
        mc.parent(_loc0_out, loc_list[-1])
        mc.pointConstraint(_loc0_out,loc_list[-3],loc_list[-2]+"_Con",mo=True,skip=["x","z"])
        
        oa_list = self.org_attr , [fc.inn,fc.mid,fc.out]
        _loc_list = [loc_list[0],loc_list[1],loc_list[3],loc_list[-1]] , [loc_list[0],loc_list[3],loc_list[-1]]
        
        for oa_l,_l_l,_sn,_at,_dv in zip(oa_list,_loc_list,["",fc.rot],["translateY","rotateZ"],[[1,-1],[45, -45]]):
            for oa,loc in zip(oa_l,_l_l):
                for pn,value in zip([fc.pos,fc.neg],_dv):
                    _attr = con.lname(prefix,oa,_sn,tag,pn)
                    mc.addAttr(lstatic,ln=_attr,at="float",dv=0,k=True,min=0)
                    dr = con.lAttr(lstatic,_attr)
                    grp = con.emptyGroup(loc,[oa+_sn+pn])[0]
                    dn = con.lAttr(grp,_at)
                    mc.setDrivenKeyframe(dn,cd=dr,dv=0,v=0,itt="linear",ott="spline")
                    mc.setDrivenKeyframe(dn,cd=dr,dv=10,v=value,itt="linear",ott="spline")

                    mc.setAttr(con.lname(grp,_at)+".postInfinity",4)
                    mc.connectAttr(con.lAttr(self.local_static,_attr),con.lAttr(lstatic,_attr))
            
        mc.delete(_crv)
        mc.parent(driCrv,lstatic)
        return lstatic
 
    def skin_joint(self,number=10):
        
        """
        
        生成 蒙皮骨骼，以及各种设置。

        :param number: 暂时没用
        :return:
        """
        
        attrlist = self.blendShape_list()
        # static_bridge = self.static_driver()
        lname = con.lname(fc.brow,con.selfFuncName(),)
        lstatic = mc.createNode(ntc.tTransform,name=con.lname(lname,fc.static),parent=self.local_static)
        
        tmp_ = con.lname("tmp",fc.brow)
        tmp_sr_crv = con.lname("tmp",fc.brow,"slider",fc.main,sc.sCrv)
        tmp_sr_crvShape = con.findRelatedShape(tmp_sr_crv)

        for lr in [fc.lf,fc.rt]:
            main_crv = con.lname(lr,tmp_,fc.main,sc.sCrv)
            ud_static_bridge = self.static_driver(lr,fc.ul, main_crv)
            sr_static_bridge = self.static_driver(lr,fc.lr,  main_crv)
            
            offest_value = mc.getAttr(con.lname(lr,"tmp_Brow_innerMax")+"."+ac.offset)
            mc.setAttr(sr_static_bridge+".ratio",offest_value*0.0045)
            
            cvs = mc.ls(main_crv+".cv[*]",fl=True)
            jotGrp = mc.createNode(ntc.tTransform,name=con.lname(lr,lname,fc.static),parent=lstatic)
            joint_list = list()
            for i,cv in enumerate(cvs):
                jot = mc.createNode(ntc.tJoint,name = con.lname(lr,lname,i+1,sc.sJot))
                joint_list.append(jot)
                x,y,z = mc.xform(cv,q=True,ws=True,t=True)
                mc.setAttr(jot+".t",x,y,z)
                mc.setAttr(jot+".radius",0.05)
                mc.parent(jot,jotGrp)
                con.emptyGroup(jot,["Zero"])
                
                mc.addAttr(jot,ln="parameter",at="long",dv=i,k=True)
                mc.setAttr(jot+".parameter",l=True)
                
                main_poci = mc.createNode(ntc.tPointOnCurveInfo,name=con.lname(lr,lname,fc.main,i,sc.sPoci))
                mc.connectAttr(con.findRelatedShape(main_crv)+".ws",main_poci+".ic")
                mc.setAttr(main_poci+".pr",i)

                for tag in [fc.up,fc.lo]:
                    
                    mc.addAttr(jot,ln=tag,at='float',dv=0,max=1,min=0,k=True)
                    
                    up_poci = mc.createNode(ntc.tPointOnCurveInfo,name=con.lname(lr,lname,tag,i,sc.sPoci))
                    mc.connectAttr(con.findRelatedShape(con.lname(main_crv,tag)) + ".ws", up_poci + ".ic")
                    mc.setAttr(up_poci + ".pr", i)
                    
                    up_pma = mc.createNode(ntc.tPlusMinusAverage,name = con.lname(lr,lname,tag,i,sc.sPma))
                    mc.connectAttr(up_poci+".p",up_pma+".input3D[0]")
                    mc.connectAttr(main_poci+".p",up_pma+".input3D[1]")
                    mc.setAttr(up_pma+".op",2)
                    
                    up_md = mc.createNode(ntc.tMultiplyDivide,name=con.lname(lr,lname,tag,i,sc.sMd))
                    mc.connectAttr(up_pma+'.output3D',up_md+".i1")
                    
                    ud_con = mc.createNode(ntc.tCondition, name=con.lname(lname, i, sc.sCon))
                    mc.connectAttr(ud_static_bridge + ".index_%s" % i, con.lAttr(ud_con, "ft"))
                    mc.setAttr(ud_con + ".st", 0)
                    mc.setAttr(ud_con+".op",2)
                    
                    absMd = mc.createNode(ntc.tMultiplyDivide,name=con.lname(lname,i,sc.sMd))
                    mc.connectAttr(ud_con+".ocr",absMd+".i1x")
                    mc.connectAttr(absMd+".ox",con.lAttr(jot, tag))
                    
                    if tag == fc.up:
                        mc.connectAttr(ud_static_bridge + ".index_%s" % i,ud_con+".ctr")
                        mc.setAttr(ud_con+".cfr",0)
                        mc.setAttr(absMd + ".i2x", 1)
                    else:
                        mc.connectAttr(ud_static_bridge + ".index_%s" % i,ud_con+".cfr")
                        mc.setAttr(ud_con+".ctr",0)
                        mc.setAttr(absMd + ".i2x", -1)

                    for al in ["x","y","z"]:
                        
                        mc.connectAttr(con.lAttr(jot, tag),up_md+".i2"+al)
                    
                    grp = con.emptyGroup(jot,[tag])[0]
                    mc.connectAttr(up_md+".o",grp+".t")
                    
                # --- sr
                par = con.getObjInCrvParameter(tmp_sr_crv,cv)
                
                sr_main_poci = mc.createNode(ntc.tPointOnCurveInfo,name=con.lname(lr,lname,"sr",i,sc.sPoci))
                mc.connectAttr(tmp_sr_crvShape+".ws",sr_main_poci+".ic")
                mc.setAttr(sr_main_poci+".pr",par)
                
                for tag in [fc.lf, fc.rt]:
                    mc.addAttr(jot,ln=tag,at='float',dv=0,max=1,min=0,k=True)
                    
                    abs_mdl = mc.createNode(ntc.tMultDoubleLinear,name=con.lname(lname,tag,i,sc.sMdl))
                    mc.connectAttr(con.lAttr(jot,tag),abs_mdl+'.i1')
                    
                    v_adl = mc.createNode(ntc.tAddDoubleLinear,name=con.lname(lname,tag,i,sc.sAdl))
                    mc.setAttr(v_adl+".i1",par,l=True)
                    mc.connectAttr(abs_mdl+".o",v_adl+'.i2')

                    lf_poci =mc.createNode(ntc.tPointOnCurveInfo,name = con.lname(lname,tag,i,sc.sPoci))
                    mc.connectAttr(tmp_sr_crvShape+".ws",lf_poci+".ic")
                    mc.setAttr(lf_poci+".top",1)
                    mc.connectAttr(v_adl+'.o',lf_poci+".pr")
                    
                    v_pma = mc.createNode(ntc.tPlusMinusAverage,name = con.lname(lname,tag,i,sc.sPma))
                    mc.connectAttr(lf_poci+".p",v_pma+'.i3[0]')
                    mc.connectAttr(sr_main_poci+".p",v_pma+".i3[1]")
                    mc.setAttr(v_pma+".op",2)
                    
                    v_con = mc.createNode(ntc.tCondition,name = con.lname(lname,tag,i,sc.sCon))
                    mc.connectAttr(sr_static_bridge+".index_%s"%i,v_con+".ft")
                    mc.setAttr(v_con+".st",0)
                    mc.setAttr(v_con+".op",2)
                    
                    if tag == fc.lf:
                        mc.connectAttr(sr_static_bridge+".index_%s"%i,v_con+".cfr")
                        mc.setAttr(v_con+".ctr",0)
                    else:
                        mc.connectAttr(sr_static_bridge+".index_%s"%i,v_con+".ctr")
                        mc.setAttr(v_con + ".cfr", 0)
                        
                    if lr == fc.lf:
                        mc.setAttr(abs_mdl+".i2",1)
                    else:
                        mc.setAttr(abs_mdl+".i2",-1)
                        
                    mc.connectAttr(v_con+".ocr",con.lAttr(jot,tag))
                    
                    grp = con.emptyGroup(jot,[tag])[0]
                    mc.connectAttr(v_pma+".o3",grp+".t")
            
            mc.sets(joint_list,include=self.local_sets)
        return
    
    def control(self):
        
        """
        生成 控制器，链接到 local bridge。
        :return:
        """
        big_control = self.org_attr
        for lr in [fc.lf,fc.rt]:
            ratio_yz = mc.getAttr(con.lname(lr,"tmp_Brow_Main_crv")+".UpLo_"+ac.offset)*0.0009
            ratio_x = mc.getAttr(con.lname(lr,"tmp_Brow_innerMax") +"." + ac.offset) * 0.001
            
            bctr = cr.objToControl(con.lname(lr,"tmp_Brow",big_control[2]),
                                   name=con.lname(lr,fc.brow,fc.root),colorId=13,ctrlShape="cube")
            if lr == fc.rt:
                con.localMirror(bctr)
            mc.parent(bctr,self.local_toParent)
            mc.setAttr(bctr+".s",ratio_yz,ratio_yz,ratio_yz)
            cr.scale(bctr,10,3,1)
            bctr_grp = con.emptyGroup(bctr)
            mc.setAttr(bctr_grp[1]+".ty",8)
            con.lockHideAttr(bctr,ignore=["tx",'ty'])
            
            ctr_list = list()
            for bc in big_control:
                tmp = con.lname(lr,"tmp_Brow",bc)
                
                ctr = cr.objToControl(tmp,name=con.lname(lr,fc.brow,bc),colorId=17,scale=4,
                                      ctrlShape="round_rectangle")
                cr.rotate(ctr,x=90)
                cr.scale(ctr, 2, 0.5, 1)

                ctr_list.append(ctr)
                if lr == fc.rt:
                    con.localMirror(ctr)
                grp = con.emptyGroup(ctr)
                mc.setAttr(grp[0]+".sx",ratio_x)
                mc.setAttr(grp[0]+".sy",ratio_yz)
                mc.setAttr(grp[0]+".sz",ratio_yz)
                mc.parent(grp[0],bctr)
                
                loc = con.objToLocator(ctr,con.lname(lr,fc.brow,bc,"ctl"))
                mc.parent(loc,self.local_static)
                con.emptyGroup(loc)
                mc.connectAttr(ctr+".t",loc+".t")
                mc.connectAttr(ctr+".r",loc+".r")
                mc.connectAttr(ctr+".s",loc+".s")
                mc.parent(con.lname(lr, fc.brow, bc, sc.sLoc,"Zero"),loc)

                
                # if bc == fc.innSup:
                #     con.lockHideAttr(ctr, ignore=["tx", 'ty',"tz"])
                # else:
                #     con.lockHideAttr(ctr, ignore=["tx", 'ty',"tz", 'rz', "sx"])

                # print [fc.ul,fc.lr]*2,["ty","tx","rz","sx"],[[1,-1]]*3+[[4, 1]],[""]*2+[fc.rot]*2
                
                # connect to static
                # for _ul,_a,_dv,_sn in zip([fc.ul,fc.lr]*2,["ty","tx","rz","sx"],
                #                           [[10,-10],[10,-10],[45,-45],[2,0.5]],[""]*2+[fc.rot]*2):
                #     for _pn,_v in zip([fc.pos,fc.neg],_dv):
                #         # for _sn,_rd in zip(["",fc.rot],[1,45]):
                #         dr = con.lAttr(ctr,_a)
                #         dr_bc = con.lAttr(bctr, _a)
                #         dn = con.lAttr(self.local_static,con.lname(lr,bc,_sn,_ul,_pn))
                #         if _a == "ty" or _a == "tx":
                #             if bc != fc.innSup:
                #                 mc.setDrivenKeyframe(dn, cd=dr_bc, dv=0, v=0, itt="spline", ott="spline")
                #                 mc.setDrivenKeyframe(dn,cd=dr_bc,dv=_v,v=10,itt="spline",ott="spline")
                #
                #         if _a == "sx":
                #             mc.setDrivenKeyframe(dn, cd=dr, dv=1, v=0, itt="spline", ott="spline")
                #         else:
                #             mc.setDrivenKeyframe(dn,cd=dr,dv=0,v=0,itt="spline",ott="spline")
                #         mc.setDrivenKeyframe(dn,cd=dr,dv=_v,v=10,itt="spline",ott="spline")
                #
                #         dn_sdk = con.lname(self.local_static,con.lname(lr,bc,_sn,_ul,_pn))
                #         if _pn == fc.pos:
                #             mc.setAttr(dn_sdk+".postInfinity",4)
                #         else:
                #             mc.setAttr(dn_sdk+".preInfinity",4)
            
            
            _loc0_out = con.objToType(ctr_list[1], name=ctr_list[0] + "_out", mode=2)
            mc.parent(_loc0_out, ctr_list[0])
            _loc1_out = con.objToType(ctr_list[1], name=ctr_list[2] + "_out", mode=2)
            mc.parent(_loc1_out, ctr_list[2])
            mc.pointConstraint(_loc0_out, _loc1_out, ctr_list[1] + "_Con", mo=True, skip=["x",])
            
            con.changColor(ctr_list[1],18)
            cr.scaleXYZ(ctr_list[1],0.8)
        return
    
    def create(self):
        try:
            # self.skin_joint()
            self.bezier_correct()
            # self.control()
            self.hide_doDelete()

            print " - Brow Rig Complete - "
        except:
            traceback.print_exc()
        return
    
    def get_mian_crv(self):
        tmp_ = con.lname("tmp", fc.brow)
        return  [con.lname(lr, tmp_, fc.main, sc.sCrv)for lr in [fc.lf, fc.rt]]
    def bezier_correct(self):
        # self.blendShape_list()
        
        pro_value = 0.001
        
        mian_crv = self.get_mian_crv()
        center_jot = mc.createNode(ntc.tJoint,name= con.lname(fc.brow,fc.mid,sc.sJot),parent=self.local_static)
        cjot_g = con.emptyGroup(center_jot)
        
        for crv,lr in zip(mian_crv,[fc.lf,fc.rt]):
            # lname =
            ratio_yz = mc.getAttr(con.lname(lr,"tmp_Brow_Main_crv")+".UpLo_"+ac.offset)*pro_value
            ratio_x = mc.getAttr(con.lname(lr,"tmp_Brow_innerMax") +"." + ac.offset) * pro_value
            
            _crv = con.copyCurve(crv,con.lname(lr,fc.brow,fc.main,"Bezier",sc.sCrv))
            mc.parent(_crv,self.local_static)
            # _crv2 = con.copyCurve(crv,con.lname(lr,fc.brow,fc.main,sc.sCrv))
            # _crv_up = con.copyCurve(con.lname(crv,fc.up),name=con.lname(lr,fc.brow,fc.up,sc.sCrv))
            # _crv_lo = con.copyCurve(con.lname(crv,fc.lo),name=con.lname(lr,fc.brow,fc.lo,sc.sCrv))
            _crv_up = con.lname(crv,fc.up)
            _crv_lo = con.lname(crv,fc.lo)
            # print _crv
            mel.eval("rebuildCurve -ch 1 -rpo 1 -rt 0 -end 1 -kr 0 -kcp 0 -kep 1 -kt 0 -s 2 -d 3 -tol 0.01 %s;"%_crv)
            mc.select(_crv)
            mc.nurbsCurveToBezier()
            clu_grp = mc.createNode(ntc.tTransform,name = con.lname(lr,fc.brow,sc.sClu,sc.sGrp),parent=self.local_static)
            loc_list = []
            locgrp_list = []
            for i,cv in enumerate(mc.ls(_crv+".cv[*]",fl=True),1):
                _lname = con.lname(lr,fc.brow,i)
                clu = mc.cluster(cv,name=con.lname(_lname,sc.sClu))
                mc.hide(clu[1])
                clu_zero = con.emptyGroup(clu[1],["Zero"])[0]
                
                loc = mc.spaceLocator(name=con.lname(_lname,sc.sLoc))[0]
                mc.parent(loc,clu_grp)
                mc.hide(loc)
                x, y, z = mc.xform(clu[1], q=True, rp=True)
                mc.setAttr(loc+".t",x,y,z)
                locgrp_list.append(con.emptyGroup(loc,["Zero"])[0])
                mc.parent(clu_zero,loc)
                
                loc_list.append(loc)
                
                # self.point_vector(loc,_lname,i,crv,_crv_up,fc.up)
                # self.point_vector(loc, _lname, i, crv, _crv_lo,fc.lo)
            bctr = cr.objToControl(con.lname(lr, "tmp_Brow", fc.mid),
                                   name=con.lname(lr, fc.brow, fc.root), colorId=13, ctrlShape="cube")

            mc.parent(bctr, self.local_toParent)
            mc.setAttr(bctr + ".s", ratio_x, ratio_yz, ratio_yz)
            cr.scale(bctr, 10, 3, 1)
            bctr_grp = con.emptyGroup(bctr)
            if lr == fc.rt:
                con.localMirror(bctr)
            root_loc = con.objToLocator(bctr, name=con.lname(lr, fc.brow, fc.root), parent=bctr)
            dri_loc_grp = con.emptyGroup(root_loc)
            for at in ["t", "r", "s"]:
                mc.connectAttr(con.lAttr(bctr, at), con.lAttr(root_loc, at))
            mc.parent(dri_loc_grp[0],self.local_static)
            con.lockHideAttr(bctr, ignore=["tx", "ty", "tz"])

            # dri_loc_grp = mc.createNode(ntc.tTransform,name=con.lname(lr,fc.brow,"driver",sc.sLoc,sc.sGrp),parent=self.local_static)
            dri_loc_list = []
            for tag in [fc.inn,fc.innSup,fc.mid,fc.out]:
                tmp = con.lname(lr,con.lname("tmp", fc.brow),tag)
                ctr = cr.objToControl(tmp,name=con.lname(lr,fc.brow,tag),colorId=17,scale=4,
                                      ctrlShape="round_rectangle")
                
                cr.rotate(ctr,x=90)
                cr.scale(ctr, 2, 0.5, 1)
                
                dri_loc = con.objToLocator(tmp,name=con.lname(lr,fc.brow,tag),parent=ctr)
                # mc.parent(dri_loc,dri_loc_grp)

                dri_g = con.emptyGroup(ctr)
                mc.setAttr(dri_g[0]+".sx",ratio_x)
                mc.setAttr(dri_g[0]+".sy",ratio_yz)
                mc.setAttr(dri_g[0]+".sz",ratio_yz)
                mc.parent(dri_g[0], bctr)
                if lr == fc.rt:
                    con.localMirror(dri_g[0])
                loc_g = con.emptyGroup(dri_loc)
                mc.parent(loc_g[0],root_loc)
                
                for at in ["t","r","s"]:
                    mc.connectAttr(con.lAttr(ctr+"_Sdk",at),con.lAttr(dri_loc+"_Sdk",at))
                    mc.connectAttr(con.lAttr(ctr,at),con.lAttr(dri_loc,at))
                
                if tag == fc.inn:
                    sec_ctr = cr.objToControl(ctr, name=con.lname(lr, fc.brow, tag+"1",), colorId=18, scale=4,
                                          )
                    cr.rotate(sec_ctr, x=90)
                    cr.scale(sec_ctr, 1, 0.4, 1)

                    # cr.changColor(sec_ctr,18)
                    mc.parent(sec_ctr,ctr)
                    con.channelAttrToDefault(sec_ctr)
                    _dri_loc = con.objToLocator(dri_loc, name=con.lname(lr, fc.brow, tag+"1"), parent=dri_loc)
                    # mc.parent(_dri_loc,dri_loc)
                    for at in ["t", "r", "s"]:
                        # mc.connectAttr(con.lAttr(ctr + "_Sdk", at), con.lAttr(dri_loc + "_Sdk", at))
                        mc.connectAttr(con.lAttr(sec_ctr, at), con.lAttr(_dri_loc, at))
                    # dri_loc = _dri_loc
                    con.lockHideAttr(sec_ctr, ignore=["tx", "ty", "tz"])

                dri_loc_list.append(dri_loc)
                con.lockHideAttr(ctr,["sx","sy","sz","v"])
            
            # 1
            _trans = con.emptyGroup(loc_list[0],["pc"])[0]
            mc.pointConstraint(_dri_loc,_trans,mo=True)
            # _trans = con.emptyGroup(loc_list[0], ["csr","pot"])
            # mc.setAttr(_trans[0] + ".s", ratio_x, ratio_yz, ratio_yz)
            # mc.connectAttr(_dri_loc + ".t", _trans[1] + ".t")
            # 2
            _trans = con.emptyGroup(loc_list[1], ["pc"])[0]
            mc.parentConstraint(dri_loc_list[0],dri_loc_list[2],_trans,mo=True,sr=[ "x", "y", "z"],st=["x"])
            _trans = con.emptyGroup(loc_list[1], ["pt"])[0]
            mc.pointConstraint(dri_loc_list[0],dri_loc_list[2],_trans,mo=True,sk=["y", "z"])
            _trans1 = mc.createNode(ntc.tTransform,name= con.lname(loc_list[1],"cor"),parent=dri_loc_list[1])
            _trans1_g = con.emptyGroup(_trans1,["Zero"])
            mc.parent(_trans1_g[0],_trans)
            mc.connectAttr(dri_loc_list[1]+".t",_trans1+".t")
            # mc.pointConstraint(dri_loc_list[1],_trans1,mo=True)
            _trans = con.emptyGroup(loc_list[1], ["csr"])
            mc.parent(_trans,_trans1)
            
            # 3
            _trans = con.emptyGroup(loc_list[2], ["pc"])[0]
            mc.parentConstraint( dri_loc_list[2], _trans, mo=True, sr=["x", "y", "z"], st=["x"])
            _trans = con.emptyGroup(loc_list[2], ["pt"])[0]
            mc.pointConstraint(dri_loc_list[2],_trans,mo=True,sk=["y", "z"])
            # 4
            _trans = con.emptyGroup(loc_list[3],["pc"])[0]
            mc.pointConstraint(dri_loc_list[2],_trans,mo=True)
            # 5
            _trans = con.emptyGroup(loc_list[4], ["pc"])[0]
            mc.parentConstraint( dri_loc_list[2], _trans, mo=True, sr=["x", "y", "z"], st=["x"])
            _trans = con.emptyGroup(loc_list[4], ["pt"])[0]
            mc.pointConstraint(dri_loc_list[2],_trans,mo=True,sk=["y", "z"])
            # 6
            _trans = con.emptyGroup(loc_list[5], ["pc"])[0]
            mc.parentConstraint(dri_loc_list[2],dri_loc_list[3],_trans,mo=True,sr=[ "x", "y", "z"],st=["x"])
            _trans = con.emptyGroup(loc_list[5], ["pt"])[0]
            mc.pointConstraint(dri_loc_list[2],dri_loc_list[3],_trans,mo=True,sk=["y","z"])
            # 7
            _trans = con.emptyGroup(loc_list[6],["pc"])[0]
            mc.pointConstraint(dri_loc_list[3],_trans,mo=True)
            # -----
            dr_bc = con.lAttr(bctr, "ty")
            mc.setAttr(dr_bc,-10)
            for clu_loc in loc_list:
                up_dis,lo_dis = self.bezier_driver_value(clu_loc,crv,con.lname(lr,fc.brow,tag,sc.sLoc))
                pt = mc.xform(clu_loc, q=True, ws=True, t=True)
                cpt = con.getObjInCrvPoint(_crv_lo,clu_loc)
                # dr_value = -con.getObjInCrvDistance(_crv_lo,clu_loc)
                dr_value = cpt[1]-pt[1]-up_dis

                _trans = con.emptyGroup(clu_loc,["Sdk"])[0]
                dn = con.lAttr(_trans,"ty")
                mc.setDrivenKeyframe(dn, cd=dr_bc, dv=0, v=0, itt="spline", ott="spline")
                mc.setDrivenKeyframe(dn, cd=dr_bc, dv=-10, v=dr_value, itt="spline", ott="spline")
            mc.setAttr(dr_bc,0)
            
            jot_crv = con.copyCurve(crv,con.lname(lr,fc.brow,fc.main,"joint",sc.sCrv))
            mc.parent(jot_crv,self.local_static)
            mel.eval("rebuildCurve -ch 1 -rpo 1 -rt 0 -end 1 -kr 0 -kcp 0 -kep 1 -kt 0 -s 4 -d 3 -tol 0.01 %s;"%jot_crv)
            mc.wire(jot_crv,w=_crv)
            _crvShape = con.findRelatedShape(jot_crv)
            jot_grp = mc.createNode(ntc.tTransform,name=con.lname(lr,sc.sJot,sc.sGrp),parent=self.local_static)
            jot_list = []
            for i, cv in enumerate(mc.ls(crv + ".cv[*]", fl=True), 1):
                
                par = con.getObjInCrvParameter(_crv,cv,)
                
                jot = mc.createNode(ntc.tJoint,name=con.lname(_lname,i,sc.sJot),parent=jot_grp)
                
                jot_poci = mc.createNode(ntc.tPointOnCurveInfo,name = con.lname(jot,sc.sPoci))
                mc.connectAttr(_crvShape+".ws",jot_poci+".ic")
                mc.setAttr(jot_poci+".pr",par)
                
                _jot_grp = con.emptyGroup(jot,["Zero","pot"])
                mc.connectAttr(jot_poci+".p",_jot_grp[1]+".t")

                jot_list.append(jot)
            
            mc.pointConstraint(jot_list[0],cjot_g[1],mo=False)
        return
    
    def _sdk(self,dn,dr_bc,value):
        mc.setDrivenKeyframe(dn, cd=dr_bc, dv=0, v=0, itt="spline", ott="spline")
        mc.setDrivenKeyframe(dn, cd=dr_bc, dv=10, v=value, itt="spline", ott="spline")

        return
    
    def bezier_driver_value(self,inobj,crv,name=""):
    
        _crv2 = crv
        _crv_up = con.lname(crv,fc.up)
        _crv_lo = con.lname(crv,fc.lo)
        
        par = con.getObjInCrvParameter(_crv2,inobj)
        
        main_poci = mc.createNode(ntc.tPointOnCurveInfo, name=con.lname(name, fc.main, sc.sPoci))
        mc.connectAttr(con.findRelatedShape(_crv2) + ".ws", main_poci + ".ic")
        mc.setAttr(main_poci + ".pr", par)
        
        up_poci = mc.createNode(ntc.tPointOnCurveInfo, name=con.lname(name, fc.up,  sc.sPoci))
        mc.connectAttr(con.findRelatedShape(_crv_up) + ".ws", up_poci + ".ic")
        mc.setAttr(up_poci + ".pr", par)
        
        lo_poci = mc.createNode(ntc.tPointOnCurveInfo, name=con.lname(name,fc.lo, sc.sPoci))
        mc.connectAttr(con.findRelatedShape(_crv_lo) + ".ws", lo_poci + ".ic")
        mc.setAttr(lo_poci + ".pr", par)
        
        # print mc.getAttr(main_poci+".p")
        point = mc.getAttr(main_poci+".p")[0][1]
        up_dis = abs(mc.getAttr(up_poci+".p")[0][1] - point)
        lo_dis = -abs(mc.getAttr(lo_poci+".p")[0][1] - point)
        
        mc.delete(main_poci,up_poci,lo_poci)
        return up_dis,lo_dis

    def point_vector(self,inobj,name,i,main_crv,ul_crv,tag):
        
        # if "ratio" not in mc.listAttr(ul_crv):
        #     mc.addAttr(ul_crv,ln="ratio",at = "float",dv=1,min=0,k=True)
        #
        if ("index_%s" % i) not in mc.listAttr(main_crv):
            mc.addAttr(main_crv, ln="index_%s" % i, at="float", dv=0, k=True)
        # ratio_mdl = mc.createNode(ntc.tMultDoubleLinear, name=con.lname(name, i, sc.sMdl))
        # # mc.connectAttr(npoc+".py",ratio_mdl+".i1")
        # mc.connectAttr(ul_crv + ".ratio", ratio_mdl + ".i2")
        # mc.connectAttr(ratio_mdl + ".o", con.lAttr(ul_crv, "index_%s" % i))
        
        mc.addAttr(inobj, ln=tag, at='float', dv=0, max=1, min=0, k=True)
        
        main_poci = mc.createNode(ntc.tPointOnCurveInfo, name=con.lname(name, fc.main, i, sc.sPoci))
        mc.connectAttr(con.findRelatedShape(main_crv) + ".ws", main_poci + ".ic")
        mc.setAttr(main_poci + ".pr", i)
    
        up_poci = mc.createNode(ntc.tPointOnCurveInfo, name=con.lname(name, tag, i, sc.sPoci))
        mc.connectAttr(con.findRelatedShape(ul_crv) + ".ws", up_poci + ".ic")
        mc.setAttr(up_poci + ".pr", i)
    
        up_pma = mc.createNode(ntc.tPlusMinusAverage, name=con.lname(name, tag, i, sc.sPma))
        mc.connectAttr(up_poci + ".p", up_pma + ".input3D[0]")
        mc.connectAttr(main_poci + ".p", up_pma + ".input3D[1]")
        mc.setAttr(up_pma + ".op", 2)
    
        up_md = mc.createNode(ntc.tMultiplyDivide, name=con.lname(name, tag, i, sc.sMd))
        mc.connectAttr(up_pma + '.output3D', up_md + ".i1")
    
        ud_con = mc.createNode(ntc.tCondition, name=con.lname(name, i, sc.sCon))
        mc.connectAttr(main_crv + ".index_%s" % i, con.lAttr(ud_con, "ft"))
        mc.setAttr(ud_con + ".st", 0)
        mc.setAttr(ud_con + ".op", 2)
    
        absMd = mc.createNode(ntc.tMultiplyDivide, name=con.lname(name, i, sc.sMd))
        mc.connectAttr(ud_con + ".ocr", absMd + ".i1x")
        mc.connectAttr(absMd + ".ox", con.lAttr(inobj, tag))
    
        if tag == fc.up:
            mc.connectAttr(main_crv + ".index_%s" % i, ud_con + ".ctr")
            mc.setAttr(ud_con + ".cfr", 0)
            mc.setAttr(absMd + ".i2x", 1)
        else:
            mc.connectAttr(main_crv + ".index_%s" % i, ud_con + ".cfr")
            mc.setAttr(ud_con + ".ctr", 0)
            mc.setAttr(absMd + ".i2x", -1)
    
        for al in ["x", "y", "z"]:
            mc.connectAttr(con.lAttr(inobj, tag), up_md + ".i2" + al)
    
        grp = con.emptyGroup(inobj, [tag])[0]
        mc.connectAttr(up_md + ".o", grp + ".t")
        return
    
    def slider_driver(self,inobj,name,i):
        #tmp_Brow_slider_Main_crv
        tmp_sr_crv = con.lname("tmp",fc.brow,"slider",fc.main,sc.sCrv)
        sr_crv = con.copyCurve(tmp_sr_crv,con.lname(fc.brow,"slider",fc.main,sc.sCrv))
        sr_crvShape = con.findRelatedShape(sr_crv)
        par = con.getObjInCrvParameter(sr_crv, inobj)
    
        sr_main_poci = mc.createNode(ntc.tPointOnCurveInfo, name=con.lname(name, "sr", i, sc.sPoci))
        mc.connectAttr(sr_crvShape + ".ws", sr_main_poci + ".ic")
        mc.setAttr(sr_main_poci + ".pr", par)
    
        for tag in [fc.lf, fc.rt]:
            mc.addAttr(inobj, ln=tag, at='float', dv=0, max=1, min=0, k=True)
        
            abs_mdl = mc.createNode(ntc.tMultDoubleLinear, name=con.lname(name, tag, i, sc.sMdl))
            mc.connectAttr(con.lAttr(inobj, tag), abs_mdl + '.i1')
        
            v_adl = mc.createNode(ntc.tAddDoubleLinear, name=con.lname(name, tag, i, sc.sAdl))
            mc.setAttr(v_adl + ".i1", par, l=True)
            mc.connectAttr(abs_mdl + ".o", v_adl + '.i2')
        
            lf_poci = mc.createNode(ntc.tPointOnCurveInfo, name=con.lname(name, tag, i, sc.sPoci))
            mc.connectAttr(sr_crvShape + ".ws", lf_poci + ".ic")
            mc.setAttr(lf_poci + ".top", 1)
            mc.connectAttr(v_adl + '.o', lf_poci + ".pr")
        
            v_pma = mc.createNode(ntc.tPlusMinusAverage, name=con.lname(name, tag, i, sc.sPma))
            mc.connectAttr(lf_poci + ".p", v_pma + '.i3[0]')
            mc.connectAttr(sr_main_poci + ".p", v_pma + ".i3[1]")
            mc.setAttr(v_pma + ".op", 2)
        
            v_con = mc.createNode(ntc.tCondition, name=con.lname(name, tag, i, sc.sCon))
            mc.connectAttr(sr_static_bridge + ".index_%s" % i, v_con + ".ft")
            mc.setAttr(v_con + ".st", 0)
            mc.setAttr(v_con + ".op", 2)
        
            if tag == fc.lf:
                mc.connectAttr(sr_static_bridge + ".index_%s" % i, v_con + ".cfr")
                mc.setAttr(v_con + ".ctr", 0)
            else:
                mc.connectAttr(sr_static_bridge + ".index_%s" % i, v_con + ".ctr")
                mc.setAttr(v_con + ".cfr", 0)
        
            if lr == fc.lf:
                mc.setAttr(abs_mdl + ".i2", 1)
            else:
                mc.setAttr(abs_mdl + ".i2", -1)
        
            mc.connectAttr(v_con + ".ocr", con.lAttr(inobj, tag))
        
            grp = con.emptyGroup(inobj, [tag])[0]
            mc.connectAttr(v_pma + ".o3", grp + ".t")
        return
if __name__ == '__main__':
    pass